<?php

namespace app\common\Attribute;

use PhpParser\Error;
use PhpParser\NodeTraverser;
use PhpParser\NodeVisitor\NameResolver;
use PhpParser\PrettyPrinter;
use ReflectionClass;
use ReflectionMethod;
use RecursiveDirectoryIterator;
use RecursiveIteratorIterator;
use RegexIterator;
use PhpParser\NodeFinder;
use PhpParser\Node\Stmt\Class_;
use PhpParser\Node\Stmt\ClassMethod;
use PhpParser\Node;
use PhpParser\Node\Stmt\Trait_;

class CodeAnalyzer
{
    private array $directories;
    private array $results = [];
    private array $phpFiles = [];
    private $parser;
    private array $namespaceMap = [];

    // RequestMethod属性的完整类名列表（支持多个属性）
    private const REQUEST_METHOD_ATTRIBUTE = [
        'app\\common\\Attribute\\RequestMethod',
        'app\\common\\Attribute\\RequestTitle',
        'app\\common\\Attribute\\ClassTitle',
    ];

    public function __construct(array $directories)
    {
        $this->directories = $directories;
        $this->initParser();
    }

    /**
     * 初始化PHP解析器
     */
    private function initParser(): void
    {
        $this->parser = new \PhpParser\Parser\Php7(new \PhpParser\Lexer());
    }

    /**
     * 扫描目录并分析PHP文件
     * 
     * @return array 分析结果
     */
    public function analyze(): array
    {
        // 构建命名空间到文件的映射
        $this->buildNamespaceMap();

        foreach ($this->directories as $group => $directory) {
            $this->results[$group] = [];
            $this->findPhpFiles($directory, $group);
        }

        $this->parseFiles();
        $this->sortResultsAlphabetically();
        return $this->results;
    }

    /**
     * 构建命名空间到文件的映射
     */
    private function buildNamespaceMap(): void
    {
        foreach ($this->directories as $directory) {
            if (!is_dir($directory)) {
                continue;
            }

            $iterator = new RecursiveIteratorIterator(
                new RecursiveDirectoryIterator($directory, RecursiveDirectoryIterator::SKIP_DOTS),
                RecursiveIteratorIterator::LEAVES_ONLY
            );

            $phpFiles = new RegexIterator($iterator, '/^.+\.php$/i', RegexIterator::GET_MATCH);

            foreach ($phpFiles as $file) {
                $filePath = $file[0];
                try {
                    $code = file_get_contents($filePath);
                    $ast = $this->parser->parse($code);

                    if ($ast === null) {
                        continue;
                    }

                    $namespace = $this->extractNamespace($ast);
                    if ($namespace) {
                        $this->namespaceMap[$namespace] = $filePath;
                    }
                } catch (Error $error) {
                    // 忽略解析错误
                }
            }
        }
    }

    /**
     * 从AST提取命名空间
     */
    private function extractNamespace(array $ast): ?string
    {
        foreach ($ast as $node) {
            if ($node instanceof \PhpParser\Node\Stmt\Namespace_) {
                return (string) $node->name;
            }
        }
        return null;
    }

    /**
     * 查找目录下的所有PHP文件
     * @throws \InvalidArgumentException 当目录不存在时
     */
    private function findPhpFiles(string $directory, string $group): void
    {
        if (!is_dir($directory)) {
            throw new \InvalidArgumentException("目录 '{$directory}' 不存在");
        }

        $iterator = new RecursiveIteratorIterator(
            new RecursiveDirectoryIterator($directory, RecursiveDirectoryIterator::SKIP_DOTS),
            RecursiveIteratorIterator::LEAVES_ONLY
        );

        $phpFiles = new RegexIterator($iterator, '/^.+\.php$/i', RegexIterator::GET_MATCH);

        foreach ($phpFiles as $file) {
            $this->phpFiles[$group][] = $file[0];
        }
    }

    /**
     * 解析PHP文件并提取类信息
     */
    private function parseFiles(): void
    {
        $traverser = new NodeTraverser();
        $traverser->addVisitor(new NameResolver());
        $nodeFinder = new NodeFinder();

        foreach ($this->phpFiles as $group => $files) {
            foreach ($files as $filePath) {
                try {
                    $code = file_get_contents($filePath);
                    $ast = $this->parser->parse($code);

                    if ($ast === null) {
                        continue;
                    }

                    $ast = $traverser->traverse($ast);
                    $classes = $nodeFinder->findInstanceOf($ast, Class_::class);

                    foreach ($classes as $classNode) {
                        $ClassTitle = (string) $classNode->namespacedName;

                        // 跳过无命名空间的类
                        if (strpos($ClassTitle, '\\') === false) {
                            continue;
                        }

                        try {
                            // 通过反射提取完整信息
                            $reflectionClass = new ReflectionClass($ClassTitle);
                            $classInfo = $this->extractClassInfo($reflectionClass);

                            // 收集类使用的所有Trait信息
                            $classInfo['traits'] = $this->collectTraitInfo($reflectionClass);

                            // 合并类和Trait的方法信息
                            $classInfo['methods'] = $this->mergeClassAndTraitMethods($reflectionClass, $classNode, $classInfo['traits']);
                            $classInfo['properties'] = $this->extractPropertiesInfo($reflectionClass);
                            $classInfo['file'] = $filePath;
                            $classInfo['group'] = $group;

                            $this->results[$group][$ClassTitle] = $classInfo;
                        } catch (\ReflectionException $e) {
                            // 反射失败时从AST节点提取信息
                            $classInfo = $this->extractClassInfoFromNode($classNode);

                            // 从AST收集Trait信息
                            $classInfo['traits'] = $this->collectTraitInfoFromAst($classNode);

                            // 合并类和Trait的方法信息
                            $classInfo['methods'] = $this->mergeClassAndTraitMethodsFromNode($classNode, $classInfo['traits']);
                            $classInfo['properties'] = $this->extractPropertiesInfoFromNode($classNode);
                            $classInfo['file'] = $filePath;
                            $classInfo['group'] = $group;

                            $this->results[$group][$ClassTitle] = $classInfo;
                        }
                    }
                } catch (Error $error) {
                    echo "解析文件 {$filePath} 时出错: {$error->getMessage()}\n";
                } catch (\Exception $e) {
                    echo "处理文件 {$filePath} 时出错: {$e->getMessage()}\n";
                }
            }
        }
    }

    /**
     * 收集类使用的所有Trait信息
     */
    private function collectTraitInfo(ReflectionClass $reflectionClass): array
    {
        $traitInfo = [];
        $traits = $reflectionClass->getTraitNames();

        foreach ($traits as $traitName) {
            try {
                $traitReflection = new ReflectionClass($traitName);

                // 提取Trait的方法
                $methods = [];
                foreach ($traitReflection->getMethods() as $method) {
                    $methods[$method->getName()] = $this->extractMethodInfo($method, $traitReflection);
                }

                // 提取Trait的属性
                $properties = [];
                foreach ($traitReflection->getProperties() as $property) {
                    $properties[$property->getName()] = [
                        'name' => $property->getName(),
                        'isStatic' => $property->isStatic(),
                        'isPublic' => $property->isPublic(),
                        'isProtected' => $property->isProtected(),
                        'isPrivate' => $property->isPrivate(),
                        'docComment' => $property->getDocComment() ?: '',
                        'parsedDocComment' => $this->parseDocComment($property->getDocComment() ?: ''),
                        'type' => $this->getPropertyType($property),
                    ];
                }

                $traitInfo[$traitName] = [
                    'name' => $traitName,
                    'file' => $traitReflection->getFileName(),
                    'docComment' => $traitReflection->getDocComment() ?: '',
                    'parsedDocComment' => $this->parseDocComment($traitReflection->getDocComment() ?: ''),
                    'methods' => $methods,
                    'properties' => $properties,
                ];
            } catch (\ReflectionException $e) {
                // 如果无法通过反射获取Trait信息，尝试从命名空间映射中解析
                if (isset($this->namespaceMap[$traitName])) {
                    $traitInfo[$traitName] = $this->parseTraitFromNamespace($traitName);
                }
            }
        }
        // dump( $traitInfo);
        return $traitInfo;
    }

    /**
     * 从AST收集Trait信息
     */
    private function collectTraitInfoFromAst(Class_ $classNode): array
    {
        $traitInfo = [];

        foreach ($classNode->stmts as $stmt) {
            if ($stmt instanceof \PhpParser\Node\Stmt\TraitUse) {
                foreach ($stmt->traits as $trait) {
                    $traitName = (string) $trait;

                    // 尝试从命名空间映射中解析Trait
                    if (isset($this->namespaceMap[$traitName])) {
                        $traitInfo[$traitName] = $this->parseTraitFromNamespace($traitName);
                    } else {
                        // 如果无法找到Trait文件，添加基本信息
                        $traitInfo[$traitName] = [
                            'name' => $traitName,
                            'file' => 'unknown',
                            'methods' => [],
                            'properties' => [],
                        ];
                    }
                }
            }
        }

        return $traitInfo;
    }

    /**
     * 从命名空间解析Trait信息
     */
    private function parseTraitFromNamespace(string $traitName): array
    {
        if (!isset($this->namespaceMap[$traitName])) {
            return [
                'name' => $traitName,
                'file' => 'unknown',
                'methods' => [],
                'properties' => [],
            ];
        }

        $filePath = $this->namespaceMap[$traitName];

        try {
            $code = file_get_contents($filePath);
            $ast = $this->parser->parse($code);

            if ($ast === null) {
                return [
                    'name' => $traitName,
                    'file' => $filePath,
                    'methods' => [],
                    'properties' => [],
                ];
            }

            $traverser = new NodeTraverser();
            $traverser->addVisitor(new NameResolver());
            $ast = $traverser->traverse($ast);

            $nodeFinder = new NodeFinder();
            $traitNodes = $nodeFinder->find($ast, function (Node $node) use ($traitName) {
                return $node instanceof Trait_ && (string) $node->namespacedName === $traitName;
            });

            foreach ($traitNodes as $traitNode) {
                // 提取Trait的方法
                $methods = [];
                foreach ($traitNode->getMethods() as $methodNode) {
                    $methodName = $methodNode->name->toString();
                    $methods[$methodName] = $this->extractMethodInfoFromNode($methodNode);
                }

                // 提取Trait的属性
                $properties = [];
                foreach ($traitNode->getProperties() as $propNode) {
                    foreach ($propNode->props as $prop) {
                        $propName = $prop->name->toString();
                        $properties[$propName] = [
                            'name' => $propName,
                            'isStatic' => $propNode->isStatic(),
                            'isPublic' => $propNode->isPublic(),
                            'isProtected' => $propNode->isProtected(),
                            'isPrivate' => $propNode->isPrivate(),
                            'docComment' => $propNode->getDocComment() ? $propNode->getDocComment()->getText() : '',
                            'parsedDocComment' => $this->parseDocComment($propNode->getDocComment() ? $propNode->getDocComment()->getText() : ''),
                            'type' => $propNode->type ? (string) $propNode->type : null,
                        ];
                    }
                }

                return [
                    'name' => $traitName,
                    'file' => $filePath,
                    'docComment' => $traitNode->getDocComment() ? $traitNode->getDocComment()->getText() : '',
                    'parsedDocComment' => $this->parseDocComment($traitNode->getDocComment() ? $traitNode->getDocComment()->getText() : ''),
                    'methods' => $methods,
                    'properties' => $properties,
                ];
            }
        } catch (Error $error) {
            // 忽略解析错误
        }

        return [
            'name' => $traitName,
            'file' => $filePath,
            'methods' => [],
            'properties' => [],
        ];
    }

    /**
     * 按类名的字母顺序对结果进行排序
     */
    private function sortResultsAlphabetically(): void
    {
        foreach ($this->results as $group => &$classes) {
            ksort($classes); // 按类名（键名）进行升序排序
        }
        unset($classes); // 释放引用

        ksort($this->results); // 对分组名进行排序
    }

    /**
     * 从反射类提取类基本信息
     */
    private function extractClassInfo(ReflectionClass $reflectionClass): array
    {
        // 提取类属性
        $attributes = [];

        // 遍历所有可能的类属性
        foreach (self::REQUEST_METHOD_ATTRIBUTE as $attributeClass) {
            $attrInstances = $reflectionClass->getAttributes($attributeClass);
            foreach ($attrInstances as $attrInstance) {
                $attrArgs = $attrInstance->getArguments();
                $attributes[] = [
                    'name' => $attributeClass,
                    'arguments' => $attrArgs,
                ];
            }
        }

        return [
            'name' => $reflectionClass->getName(),
            'namespace' => $reflectionClass->getNamespaceName(),
            'isAbstract' => $reflectionClass->isAbstract(),
            'isFinal' => $reflectionClass->isFinal(),
            'isInterface' => $reflectionClass->isInterface(),
            'isTrait' => $reflectionClass->isTrait(),
            'docComment' => $reflectionClass->getDocComment() ?: '',
            'parsedDocComment' => $this->parseDocComment($reflectionClass->getDocComment() ?: ''),
            'parentClass' => $reflectionClass->getParentClass() ? $reflectionClass->getParentClass()->getName() : '',
            'interfaces' => $reflectionClass->getInterfaceNames(),
            'traits' => [], // 将由collectTraitInfo填充
            'attributes' => $attributes, // 新增：类属性
        ];
    }

    /**
     * 从AST节点提取类基本信息（反射失败时用）
     */
    private function extractClassInfoFromNode(Class_ $classNode): array
    {
        // 修复：正确提取命名空间
        $namespace = '';
        $namespacedName = $classNode->namespacedName;
        if ($namespacedName instanceof \PhpParser\Node\Name\FullyQualified) {
            // 拆分完整类名获取命名空间（例如将 "app\admin\controller\Upload" 拆分为 "app\admin\controller"）
            $parts = $namespacedName->getParts();
            if (count($parts) > 1) {
                array_pop($parts); // 移除类名部分
                $namespace = implode('\\', $parts);
            }
        }

        // 提取类属性
        $attributes = $this->extractClassAttributesFromNode($classNode);

        return [
            'name' => (string) $classNode->namespacedName,
            'namespace' => $namespace, // 使用修复后的命名空间
            'isAbstract' => $classNode->isAbstract(),
            'isFinal' => $classNode->isFinal(),
            'isInterface' => $classNode instanceof \PhpParser\Node\Stmt\Interface_,
            'isTrait' => $classNode instanceof Trait_, // 修正判断方式
            'docComment' => $classNode->getDocComment() ? $classNode->getDocComment()->getText() : '',
            'parsedDocComment' => $this->parseDocComment($classNode->getDocComment() ? $classNode->getDocComment()->getText() : ''),
            'parentClass' => $classNode->extends ? (string) $classNode->extends : '',
            'interfaces' => array_map(fn($iface) => (string) $iface, $classNode->implements),
            'traits' => [], // 将由collectTraitInfoFromAst填充
            'attributes' => $attributes, // 新增：类属性
        ];
    }

    /**
     * 合并类和Trait的方法信息（反射方式）
     */
    private function mergeClassAndTraitMethods(ReflectionClass $reflectionClass, Class_ $classNode, array $traitInfo): array
    {
        $methods = [];
        // 首先添加类自身定义的方法
        foreach ($reflectionClass->getMethods() as $method) {
            $methodName = $method->getName();
            $declaringClass = $method->getDeclaringClass()->getName();

            // 如果方法是在Trait中声明的，跳过，因为我们会从Trait信息中添加
            if (isset($traitInfo[$declaringClass])) {
                continue;
            }

            $methods[$methodName] = $this->extractMethodInfo($method, $reflectionClass);
        }

        // 然后添加所有Trait中的方法
        foreach ($traitInfo as $traitName => $trait) {
            foreach ($trait['methods'] as $methodName => $methodInfo) {
                // 如果类中已经定义了同名方法，则跳过Trait中的方法（类方法覆盖Trait方法）
                if (isset($methods[$methodName])) {
                    // 确保isFromTrait属性设置为true
                    $methodInfo['isFromTrait'] = true;
                    $methodInfo['declaringClass'] = $traitName;
                    $methods[$methodName] = $methodInfo;
                }
            }
        }

        return $methods;
    }

    /**
     * 合并类和Trait的方法信息（AST方式）
     */
    private function mergeClassAndTraitMethodsFromNode(Class_ $classNode, array $traitInfo): array
    {
        $methods = [];

        // 首先添加类自身定义的方法
        foreach ($classNode->getMethods() as $methodNode) {
            $methodName = $methodNode->name->toString();
            $methods[$methodName] = $this->extractMethodInfoFromNode($methodNode);
        }

        // 然后添加所有Trait中的方法
        foreach ($traitInfo as $traitName => $trait) {
            foreach ($trait['methods'] as $methodName => $methodInfo) {
                // 如果类中已经定义了同名方法，则跳过Trait中的方法（类方法覆盖Trait方法）
                if (!isset($methods[$methodName])) {
                    // 确保isFromTrait属性设置为true
                    $methodInfo['isFromTrait'] = true;
                    $methodInfo['declaringClass'] = $traitName;
                    $methods[$methodName] = $methodInfo;
                }
            }
        }

        return $methods;
    }

    /**
     * 从反射方法提取单个方法信息，增加来源判断
     */
    private function extractMethodInfo(ReflectionMethod $method, ReflectionClass $currentClass): array
    {
        $attributes = [];

        // 遍历所有可能的请求方法属性
        foreach (self::REQUEST_METHOD_ATTRIBUTE as $attributeClass) {
            $attrInstances = $method->getAttributes($attributeClass);
            foreach ($attrInstances as $attrInstance) {
                $attrArgs = $attrInstance->getArguments();
                $attributes[] = [
                    'name' => $attributeClass,
                    'arguments' => $attrArgs,
                ];
            }
        }

        // 获取方法实际声明的类
        $declaringClass = $method->getDeclaringClass();
        $declaringClassTitle = $declaringClass->getName();
        $currentClassTitle = $currentClass->getName();

        // 初始化来源标识
        $isFromParent = false;
        $isFromTrait = false;

        // 判断方法是否来自父类或Trait
        if ($declaringClassTitle !== $currentClassTitle) {
            if ($declaringClass->isTrait()) {
                $isFromTrait = true; // 来自Trait
            } else {
                $isFromParent = true; // 来自父类
            }
        }

        return [
            'name' => $method->getName(),
            'isStatic' => $method->isStatic(),
            'isPublic' => $method->isPublic(),
            'isProtected' => $method->isProtected(),
            'isPrivate' => $method->isPrivate(),
            'isAbstract' => $method->isAbstract(),
            'isFinal' => $method->isFinal(),
            'isFromParent' => $isFromParent,
            'isFromTrait' => $isFromTrait,
            'declaringClass' => $declaringClassTitle,

            'docComment' => $method->getDocComment() ?: '',
            'parsedDocComment' => $this->parseDocComment($method->getDocComment() ?: ''),
            'parameters' => $this->extractMethodParameters($method),
            'attributes' => $attributes, // 保存所有属性信息
        ];
    }

    /**
     * 从AST方法节点提取单个方法信息
     */
    private function extractMethodInfoFromNode(ClassMethod $methodNode): array
    {
        // 提取属性
        $attributes = $this->extractAttributesFromNode($methodNode);

        return [
            'name' => $methodNode->name->toString(),
            'isStatic' => $methodNode->isStatic(),
            'isPublic' => $methodNode->isPublic(),
            'isProtected' => $methodNode->isProtected(),
            'isPrivate' => $methodNode->isPrivate(),
            'isAbstract' => $methodNode->isAbstract(),
            'isFinal' => $methodNode->isFinal(),
            'docComment' => $methodNode->getDocComment() ? $methodNode->getDocComment()->getText() : '',
            'parsedDocComment' => $this->parseDocComment($methodNode->getDocComment() ? $methodNode->getDocComment()->getText() : ''),
            'parameters' => $this->extractMethodParametersFromNode($methodNode),
            'isFromTrait' => false,
            'declaringClass' => '',
            'attributes' => $attributes, // 保存所有属性信息
        ];
    }

    /**
     * 从方法节点提取所有指定属性的信息
     */
    private function extractAttributesFromNode(ClassMethod $methodNode): array
    {
        $attributes = [];

        // 遍历所有属性组
        foreach ($methodNode->attrGroups as $attrGroup) {
            foreach ($attrGroup->attrs as $attr) {
                $attrName = (string) $attr->name;

                // 检查是否匹配任何指定的属性类
                foreach (self::REQUEST_METHOD_ATTRIBUTE as $requestMethodClass) {
                    $shortName = basename(str_replace('\\', '/', $requestMethodClass));

                    // 检查属性名称是否与配置中的任何属性匹配
                    if (
                        str_ends_with($attrName, '\\' . $shortName) ||
                        str_ends_with($attrName, $shortName)
                    ) {
                        // 解析属性参数
                        $arguments = [];
                        foreach ($attr->args as $arg) {
                            $argName = $arg->name ? (string) $arg->name : null;
                            $argValue = $this->getValueFromNode($arg->value);

                            if ($argName) {
                                $arguments[$argName] = $argValue;
                            } else {
                                $arguments[] = $argValue;
                            }
                        }

                        $attributes[] = [
                            'name' => $requestMethodClass,
                            'arguments' => $arguments,
                        ];
                    }
                }
            }
        }

        return $attributes;
    }

    /**
     * 解析RequestMethod属性的参数
     */
    private function parseRequestMethodArgs(array $args): array
    {
        $methods = [];
        foreach ($args as $arg) {
            $value = $this->getValueFromNode($arg->value);
            if (is_array($value)) {
                $methods = array_merge($methods, $value);
            } else {
                $methods[] = $value;
            }
        }
        return $methods;
    }

    /**
     * 从AST节点提取参数信息
     */
    private function extractMethodParametersFromNode(ClassMethod $methodNode): array
    {
        $parameters = [];
        foreach ($methodNode->params as $paramNode) {
            $paramInfo = [
                'name' => $paramNode->var->name,
                'isOptional' => $paramNode->default !== null,
                'hasDefaultValue' => $paramNode->default !== null,
            ];

            if ($paramNode->default !== null) {
                $paramInfo['defaultValue'] = $this->getValueFromNode($paramNode->default);
            }

            if ($paramNode->type !== null) {
                $paramInfo['type'] = (string) $paramNode->type;
                $paramInfo['isBuiltinType'] = !($paramNode->type instanceof \PhpParser\Node\Name);
            }

            $parameters[] = $paramInfo;
        }
        return $parameters;
    }

    /**
     * 从反射方法提取参数信息
     */
    private function extractMethodParameters(ReflectionMethod $method): array
    {
        $parameters = [];

        foreach ($method->getParameters() as $parameter) {
            $paramInfo = [
                'name' => $parameter->getName(),
                'isOptional' => $parameter->isOptional(),
                'hasDefaultValue' => $parameter->isDefaultValueAvailable(),
            ];

            if ($parameter->isDefaultValueAvailable()) {
                try {
                    $paramInfo['defaultValue'] = $parameter->getDefaultValue();
                } catch (\ReflectionException $e) {
                    $paramInfo['defaultValue'] = null;
                }
            }

            if ($parameter->hasType()) {
                $paramInfo['type'] = (string) $parameter->getType();
                $paramInfo['isBuiltinType'] = $parameter->getType()->isBuiltin();
            }

            $parameters[] = $paramInfo;
        }

        return $parameters;
    }

    /**
     * 从反射类提取属性信息
     */
    private function extractPropertiesInfo(ReflectionClass $reflectionClass): array
    {
        $properties = [];

        foreach ($reflectionClass->getProperties() as $property) {
            $properties[$property->getName()] = [
                'name' => $property->getName(),
                'isStatic' => $property->isStatic(),
                'isPublic' => $property->isPublic(),
                'isProtected' => $property->isProtected(),
                'isPrivate' => $property->isPrivate(),
                'docComment' => $property->getDocComment() ?: '',
                'parsedDocComment' => $this->parseDocComment($property->getDocComment() ?: ''),
                'type' => $this->getPropertyType($property),
            ];
        }

        return $properties;
    }

    /**
     * 获取属性类型（从反射）
     */
    private function getPropertyType(\ReflectionProperty $property): ?string
    {
        if ($property->hasType()) {
            return (string) $property->getType();
        }

        // 从注释提取类型
        $comment = $property->getDocComment() ?: '';
        if (preg_match('/@var\s+([^\s]+)/', $comment, $matches)) {
            return $matches[1];
        }

        return null;
    }

    /**
     * 从AST节点提取属性信息
     */
    private function extractPropertiesInfoFromNode(Class_ $classNode): array
    {
        $properties = [];

        foreach ($classNode->getProperties() as $propNode) {
            foreach ($propNode->props as $prop) {
                $propInfo = [
                    'name' => $prop->name->toString(),
                    'isStatic' => $propNode->isStatic(),
                    'isPublic' => $propNode->isPublic(),
                    'isProtected' => $propNode->isProtected(),
                    'isPrivate' => $propNode->isPrivate(),
                    'docComment' => $propNode->getDocComment() ? $propNode->getDocComment()->getText() : '',
                    'parsedDocComment' => $this->parseDocComment($propNode->getDocComment() ? $propNode->getDocComment()->getText() : ''),
                ];

                if ($propNode->type !== null) {
                    $propInfo['type'] = (string) $propNode->type;
                }

                $properties[$propInfo['name']] = $propInfo;
            }
        }

        return $properties;
    }


    /**
     * 从类节点提取所有指定属性的信息
     */
    private function extractClassAttributesFromNode(Class_ $classNode): array
    {
        $attributes = [];

        // 遍历所有属性组
        foreach ($classNode->attrGroups as $attrGroup) {
            foreach ($attrGroup->attrs as $attr) {
                $attrName = (string) $attr->name;

                // 检查是否匹配任何指定的属性类
                foreach (self::REQUEST_METHOD_ATTRIBUTE as $requestMethodClass) {
                    $shortName = basename(str_replace('\\', '/', $requestMethodClass));

                    // 检查属性名称是否与配置中的任何属性匹配
                    if (
                        str_ends_with($attrName, '\\' . $shortName) ||
                        str_ends_with($attrName, $shortName)
                    ) {
                        // 解析属性参数
                        $arguments = [];
                        foreach ($attr->args as $arg) {
                            $argName = $arg->name ? (string) $arg->name : null;
                            $argValue = $this->getValueFromNode($arg->value);

                            if ($argName) {
                                $arguments[$argName] = $argValue;
                            } else {
                                $arguments[] = $argValue;
                            }
                        }

                        $attributes[] = [
                            'name' => $requestMethodClass,
                            'arguments' => $arguments,
                        ];
                    }
                }
            }
        }

        return $attributes;
    }
    /**
     * 解析PHP文档注释
     * 
     * @param string $docComment 文档注释内容
     * @return array 解析结果，包含摘要、描述和标签
     */
    private function parseDocComment(string $docComment): array
    {
        if (empty($docComment)) {
            return [
                'summary' => '',
                'description' => '',
                'tags' => []
            ];
        }

        // 移除注释标记
        $content = trim(preg_replace('/^\s*\*\/|^\s*\* ?|^\/\*\*/m', '', $docComment));

        // 分割摘要和描述
        $parts = preg_split('/\n\s*\n/', $content, 2);
        $summary = $parts[0] ?? '';
        $description = $parts[1] ?? '';

        // 解析标签
        $tags = [];
        preg_match_all('/@(\w+)(?:[ \t]+([^@\n]*))?/s', $content, $matches, PREG_SET_ORDER);

        foreach ($matches as $match) {
            $tag = $match[1];
            $value = trim($match[2] ?? '');

            if (!isset($tags[$tag])) {
                $tags[$tag] = [];
            }

            $tags[$tag][] = $value;
        }

        return [
            'summary' => $summary,
            'description' => $description,
            'tags' => $tags
        ];
    }

    /**
     * 从AST节点获取值（辅助方法）
     */
    private function getValueFromNode(Node $node)
    {
        if ($node instanceof \PhpParser\Node\Scalar\String_) {
            return $node->value;
        } elseif ($node instanceof \PhpParser\Node\Scalar\LNumber) {
            return $node->value;
        } elseif ($node instanceof \PhpParser\Node\Scalar\DNumber) {
            return $node->value;
        } elseif ($node instanceof \PhpParser\Node\Expr\Array_) {
            $array = [];
            foreach ($node->items as $item) {
                $key = $item->key ? $this->getValueFromNode($item->key) : null;
                $value = $this->getValueFromNode($item->value);
                if ($key !== null) {
                    $array[$key] = $value;
                } else {
                    $array[] = $value;
                }
            }
            return $array;
        } elseif ($node instanceof \PhpParser\Node\Expr\ConstFetch) {
            return (string) $node->name;
        } elseif ($node instanceof \PhpParser\Node\Name) {
            return (string) $node;
        } else {
            return null;
        }
    }

    /**
     * 转换为JSON格式
     */
    public function toJson(): string
    {
        return json_encode($this->results, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
    }
}